package cn.iocoder.yudao.module.wms.service.rdrecord01;

import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.wms.controller.admin.pomain.vo.PomainSaveReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.pomain.vo.PomainsRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.pomain.PomainDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockLogDO;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import cn.iocoder.yudao.module.wms.service.batch.BatchService;
import cn.iocoder.yudao.module.wms.service.pomain.PomainService;
import cn.iocoder.yudao.module.wms.service.stock.StockService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord01.vo.*;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord01.Rdrecord01DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord01.Rdrecords01DO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord01.Rdrecord01Mapper;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord01.Rdrecords01Mapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*;

/**
 * 采购入库主 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class Rdrecord01ServiceImpl implements Rdrecord01Service {
    public static final String PROCESS_KEY = "rdrecord01";
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private Rdrecord01Mapper rdrecord01Mapper;
    @Resource
    private Rdrecords01Mapper rdrecords01Mapper;
    @Resource
    private BatchService batchService;
    @Resource
    private PomainService pomainService;

    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;

    @Resource
    private StockService stockService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createRdrecord01(Rdrecord01SaveReqVO createReqVO) {
        // 插入
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.POMAIN_SERIAL_PREFIX, RedisKeyConstants.SERIAL01);

        Rdrecord01DO rdrecord01 = BeanUtils.toBean(createReqVO, Rdrecord01DO.class).setStatus(BpmTaskStatusEnum.SUBMIT.getStatus()).setCode(serialNumber);;
        validateUserForCreateOrUpdate(rdrecord01);
        rdrecord01Mapper.insert(rdrecord01);

        // 插入子表
        createRdrecords01List(rdrecord01.getId(), createReqVO.getRdrecords01s());
        businessProcessing(createReqVO, createReqVO.getRdrecords01s());
            // 返回
        return rdrecord01.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord01(Rdrecord01SaveReqVO updateReqVO) {
        // 校验存在
        validateRdrecord01Exists(updateReqVO.getId());
        //获取原始表单数据
        Rdrecord01DO oldRdrecord01RespVO=getRdrecord01(updateReqVO.getId());
        // 更新
        Rdrecord01DO updateObj = BeanUtils.toBean(updateReqVO, Rdrecord01DO.class);
        rdrecord01Mapper.updateById(updateObj);
        //获取原本数据
        List<Rdrecords01DO> oldList=rdrecords01Mapper.selectListByPid(updateReqVO.getId());

        //恢复采购订单的数量和库存数量 删除库存
        if (oldList!=null)
        {
            for(Rdrecords01DO rdrecords01DO:oldList) {
                //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
                    PomainsRespVO pomainsRespVO = pomainService.findPomainsById(rdrecords01DO.getPomainsId());
                    pomainsRespVO.setUseQty(pomainsRespVO.getUseQty() - rdrecords01DO.getQty());
                    pomainService.updatePomains(pomainsRespVO);
                    //修改采购订单的主表数量
                    PomainDO pomainDO = pomainService.getPomain(pomainsRespVO.getPid());
                    pomainDO.setRkSum(pomainDO.getRkSum() - rdrecords01DO.getQty());
                    PomainSaveReqVO pomainSaveReqVO = new PomainSaveReqVO();
                    BeanUtils.copyProperties(pomainDO, pomainSaveReqVO);
                    pomainService.updatePomain(pomainSaveReqVO);

                    //删除库存
                    Rdrecords01RespVO oldRdrecords01RespVO=rdrecord01Mapper.findRdrecords01ById(rdrecords01DO.getId());
                    StockDO stockDO=new StockDO().setBatchCode(rdrecords01DO.getCbatch()).setInventoryId(oldRdrecords01RespVO.getInventoryId())
                            .setWarehouseId(oldRdrecord01RespVO.getCwhId()).setLocationId(oldRdrecords01RespVO.getCposcode());
                    stockService.restore(stockDO);
            }
        }

        // 更新子表
        if (updateReqVO.getRdrecords01s()!=null){
            updateRdrecords01List(updateReqVO.getId(), updateReqVO.getRdrecords01s());
        }

        //重新入库
        businessProcessing(updateReqVO, updateReqVO.getRdrecords01s());





    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRdrecord01(Integer id) {
        // 校验存在
        validateRdrecord01Exists(id);
        //获取原始表单数据
        Rdrecord01DO oldRdrecord01RespVO=getRdrecord01(id);
        //获取原本数据
        List<Rdrecords01DO> oldList=rdrecords01Mapper.selectListByPid(id);


        //恢复采购订单的数量和库存数量
        if (oldList!=null)
        {
            for(Rdrecords01DO rdrecords01DO:oldList) {
                //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
                PomainsRespVO pomainsRespVO = pomainService.findPomainsById(rdrecords01DO.getPomainsId());
                pomainsRespVO.setUseQty(pomainsRespVO.getUseQty() - rdrecords01DO.getQty());
                pomainService.updatePomains(pomainsRespVO);
                //修改采购订单的主表数量
                PomainDO pomainDO = pomainService.getPomain(pomainsRespVO.getPid());
                pomainDO.setRkSum(pomainDO.getRkSum() - rdrecords01DO.getQty());
                PomainSaveReqVO pomainSaveReqVO = new PomainSaveReqVO();
                BeanUtils.copyProperties(pomainDO, pomainSaveReqVO);
                pomainService.updatePomain(pomainSaveReqVO);

                //删除库存
                Rdrecords01RespVO oldRdrecords01RespVO=rdrecord01Mapper.findRdrecords01ById(rdrecords01DO.getId());
                StockDO stockDO=new StockDO().setBatchCode(rdrecords01DO.getCbatch()).setInventoryId(oldRdrecords01RespVO.getInventoryId())
                        .setWarehouseId(oldRdrecord01RespVO.getCwhId()).setLocationId(oldRdrecords01RespVO.getCposcode()).setQty(oldRdrecords01RespVO.getQty());
                stockService.restore(stockDO);
            }
        }

        // 删除
        rdrecord01Mapper.deleteById(id);
        // 删除子表
        deleteRdrecords01ByPid(id);
    }

    private void validateRdrecord01Exists(Integer id) {
        if (rdrecord01Mapper.selectById(id) == null) {
            throw exception(RDRECORD01_NOT_EXISTS);
        }
    }

    @Override
    public Rdrecord01DO getRdrecord01(Integer id) {
        return rdrecord01Mapper.selectById(id);
    }

    @Override
    public PageResult<Rdrecord01DO> getRdrecord01Page(Rdrecord01PageReqVO pageReqVO) {
        return rdrecord01Mapper.selectPage(pageReqVO);
    }

    // ==================== 子表（采购入库子） ====================

    @Override
    public List<Rdrecords01DO> getRdrecords01ListByPid(Integer pid) {
        return rdrecords01Mapper.selectListByPid(pid);
    }

    @Override
    public void updateRdrecord01Status(Rdrecord01SaveReqVO reqVO) {
        rdrecord01Mapper.updateRdrecord01Status(reqVO);
    }

    @Override
    public Rdrecord01DO findByProcessInstanceId(String processInstanceId) {
        return rdrecord01Mapper.findByProcessInstanceId(processInstanceId);
    }

    //入库操作
    public void businessProcessing(Rdrecord01SaveReqVO rdrecord01DO, List<Rdrecords01DO> rdrecords01DOList) {
            for(Rdrecords01DO rdrecords01DO:rdrecords01DOList)
            {
                //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
                PomainsRespVO pomainsRespVO=pomainService.findPomainsById(rdrecords01DO.getPomainsId());
                if ((pomainsRespVO.getQty()-pomainsRespVO.getUseQty())>=rdrecords01DO.getQty())
                {
                    pomainsRespVO.setUseQty(pomainsRespVO.getUseQty()+rdrecords01DO.getQty());
                    pomainService.updatePomains(pomainsRespVO);
                    //修改采购订单的主表数量
                    PomainDO pomainDO=pomainService.getPomain(pomainsRespVO.getPid());
                    pomainDO.setRkSum(pomainDO.getRkSum()+rdrecords01DO.getQty());
                    PomainSaveReqVO pomainSaveReqVO=new PomainSaveReqVO();
                    BeanUtils.copyProperties(pomainDO,pomainSaveReqVO);
                    pomainService.updatePomain(pomainSaveReqVO);
                }else {
                    throw exception(RDRECORD01_NUMBER_OUT);
                }

                //执行入库方法
                StockDO stockDO=new StockDO().setQty(rdrecords01DO.getQty()).setInventoryId(pomainsRespVO.getInventoryId())
                        .setWarehouseId(rdrecord01DO.getCwhId()).setLocationId(rdrecords01DO.getCposcode()).setBatchCode(rdrecords01DO.getCbatch());
                stockService.store(stockDO);

            }


    }
    //修改库存操作
    public void businessProcessingUpdate(Rdrecord01SaveReqVO rdrecord01DO, List<Rdrecords01DO> rdrecords01DOList) {
        for(Rdrecords01DO rdrecords01DO:rdrecords01DOList)
        {
            //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
            PomainsRespVO pomainsRespVO=pomainService.findPomainsById(rdrecords01DO.getPomainsId());
            if ((pomainsRespVO.getQty()-pomainsRespVO.getUseQty())>=rdrecords01DO.getQty())
            {
                pomainsRespVO.setUseQty(pomainsRespVO.getUseQty()+rdrecords01DO.getQty());
                pomainService.updatePomains(pomainsRespVO);
                //修改采购订单的主表数量
                PomainDO pomainDO=pomainService.getPomain(pomainsRespVO.getPid());
                pomainDO.setRkSum(pomainDO.getRkSum()+rdrecords01DO.getQty());
                PomainSaveReqVO pomainSaveReqVO=new PomainSaveReqVO();
                BeanUtils.copyProperties(pomainDO,pomainSaveReqVO);
                pomainService.updatePomain(pomainSaveReqVO);
            }else {
                throw exception(RDRECORD01_NUMBER_OUT);
            }

            //执行入库方法
            StockDO stockDO=new StockDO().setQty(rdrecords01DO.getQty()).setInventoryId(pomainsRespVO.getInventoryId())
                    .setWarehouseId(rdrecord01DO.getCwhId()).setLocationId(rdrecords01DO.getCposcode()).setBatchCode(rdrecords01DO.getCbatch());
            stockService.store(stockDO);

        }


    }

    @Override
    public List<Rdrecords01RespVO> findRdrecords01ByPid(Integer pid) {
        return rdrecord01Mapper.findRdrecords01ByPid(pid);
    }

    @Override
    public void process(Integer id) {
        /***
         * 启动流程
         */

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(SecurityFrameworkUtils.getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(id)));

        // 将工作流的编号，更新到 业务表单中
        rdrecord01Mapper.updateById(new Rdrecord01DO().setId(id).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));

    }


    private void createRdrecords01List(Integer pid, List<Rdrecords01DO> list) {
        list.forEach(o -> o.setPid(pid).setCbatch(batchService.generateBatch(Long.valueOf(pomainService.findPomainsById(o.getPomainsId()).getInventoryId()))));
        rdrecords01Mapper.insertBatch(list);
    }

    private void updateRdrecords01List(Integer pid, List<Rdrecords01DO> list) {
        deleteRdrecords01ByPid(pid);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createRdrecords01List(pid, list);
    }

    private void deleteRdrecords01ByPid(Integer pid) {
        rdrecords01Mapper.deleteByPid(pid);
    }


    /***
     * 数据校验
     */
    public void validateUserForCreateOrUpdate(Rdrecord01DO rdrecord01DO)
    {
        if (rdrecord01Mapper.findCountByCode(rdrecord01DO.getCode())>0)
        {
            throw exception(RDRECORD01_NOT_CODE);
        }
    }
}